﻿using System;
using System.Linq;

using Buddy.BehaviorTree;
using Buddy.CommonBot;
using Buddy.Swtor;
using Buddy.Swtor.Objects;

using WingIt;
using WingIt.Dynamics;
using WingIt.Routines.Mirrors;

using Action = Buddy.BehaviorTree.Action;

namespace WingIt.Routines
{
    [RevisionControlId("$Id: InquisitorConsularBasic.cs 686 2012-08-12 16:12:20Z Chinajade $")]
    public class InquisitorConsular : MirrorRoutine
    {
        // MAINTAINERS NOTES:
        // * You will notice that lambda expression argument names are unique (e.g., "darkWardOn", "darkWardWhen", "joltWhen"),
        //   instead of generic (e.g., "ctx", "ret", "on", "doWhen", "castWhen").  PLEASE honor this convention!
        //   This allows us to quickly localize problems when looking at user's logs.  When the BehaviorTree encounters an exception
        //   (e.g., "object not found"), the location where an exception is thrown is identifiable only through the name
        //   of the lambda expression argument.  Such is the nature of BehaviorTrees.

        #region Convenience methods
        private static float    EngagementRange(TorCharacter target)    { return (RangeAbilityReady(target) ? 1f : Global.Distance.Melee); }
        private static bool     RangeAbilityReady(TorCharacter target)  { return (Me.IsMirrorAbilityReady("Force Lightning", target) && Resource >= 30)
                                                                             || (Me.IsMirrorAbilityReady("Shock", target) && Resource >= 45); }
        #endregion

        [Behavior(BehaviorType.Pull)]
        [Class(CharacterClass.Inquisitor)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Assassin, SkillTreeId.None)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Sorcerer, SkillTreeId.None)]
        [Class(CharacterClass.Consular)]
        [Class(CharacterClass.Consular, AdvancedClass.Shadow, SkillTreeId.None)]
        [Class(CharacterClass.Consular, AdvancedClass.Sage, SkillTreeId.None)]
        public static Composite InquisitorConsular_Pull()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                CreateBTPS.BWcoreFixup_WaitForHarvestComplete(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                InquisitorConsular_Combat()
                );
        }

        [Behavior(BehaviorType.Combat)]
        [Class(CharacterClass.Inquisitor)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Assassin, SkillTreeId.None)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Sorcerer, SkillTreeId.None)]
        [Class(CharacterClass.Consular)]
        [Class(CharacterClass.Consular, AdvancedClass.Shadow, SkillTreeId.None)]
        [Class(CharacterClass.Consular, AdvancedClass.Sage, SkillTreeId.None)]
        public static Composite InquisitorConsular_Combat()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                // If our ranged attack ready, move to Distance.Ranged; otherwise move to Distance.Melee...
                CreateBTPS.MoveWithinRangeAndLoS(target => MyTarget, range => EngagementRange(MyTarget)),
                CreateBTPS.StopWithinRangeAndLoS(target => MyTarget, range => EngagementRange(MyTarget)),

                //General
                Cast("Unbreakable Will", unbreakableWillWhen => Me.IsStunned),//Insignia/2m CD
                Cast("Recklessness", recklessnessWhen => Me.ResourceStat >= 60),

                //CC
                /*Cast("Whirlwind", whirlwindOn =>
                {
                    var previousTarget = MyTarget;
                    return
                        Helpers.Targets.FirstOrDefault(
                            t =>
                            t != previousTarget && (t.Toughness != CombatToughness.Player) && !t.IsDead) ??
                        Helpers.Targets.FirstOrDefault(t => t != previousTarget);
                }, whirlwindWhen => Helpers.Targets.Count() >= 3),*/

                //Offensive
                Cast("Force Lightning"),//-30F/3S channeled
                Cast("Shock"),// Project
                Cast("Electrocute", electrocuteWhen => (MyTarget.Toughness == CombatToughness.Boss1) || (MyTarget.Toughness == CombatToughness.Strong)),
                Cast("Overload", overloadWhen => Me.MobCountAround(Global.Distance.MeleeAoE) >= 3),//Knockback
                Cast("Thrash", thrashWhen => !Me.IsMirrorAbilityReady("Shock", MyTarget) && !Me.IsMirrorAbilityReady("Force Lightning", MyTarget)), // If Shock or Force Lightning is NOT on CD, Trash should not be casted, even if enough force is available.
                Cast("Saber Strike")
                );
        }

        [Behavior(BehaviorType.OutOfCombat)]
        [Class(CharacterClass.Inquisitor)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Assassin, SkillTreeId.None)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Sorcerer, SkillTreeId.None)]
        [Class(CharacterClass.Consular)]
        [Class(CharacterClass.Consular, AdvancedClass.Shadow, SkillTreeId.None)]
        [Class(CharacterClass.Consular, AdvancedClass.Sage, SkillTreeId.None)]
        public static Composite InquisitorConsular_OutOfCombat()
        {
            // NB: Apparently, BWcore will call this routine when in combat on occasion.  It is also called while we're pulling.
            return (new PrioritySelector(
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),
                new Decorator(oocBuffWhen => !Me.IsMounted,
                    new PrioritySelector(
                        ))
                ));
        }
    }
}